package com.hulk.dryad.manage.boot.launch;

import cn.hutool.core.util.StrUtil;
import cn.hutool.system.SystemUtil;
import com.hulk.dryad.common.constant.CommonConstants;
import com.hulk.dryad.common.util.OSUtil;
import com.hulk.dryad.manage.boot.basic.launch.AbstractOnceLaunch;
import com.hulk.dryad.manage.boot.env.DryadEnv;
import net.dreamlu.mica.auto.annotation.AutoEnvPostProcessor;

import org.springframework.boot.SpringApplication;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.function.Function;

/**
 *  初始化
 *
 * @author hulk
 */
@AutoEnvPostProcessor
public class DryadLauncher extends AbstractOnceLaunch {

	public static final  String EXCLAMATION_MARK = "!";

	@Override
	public void run(ConfigurableEnvironment environment, SpringApplication application) {
		// 服务名，applicationContext.getId() 默认会是 application，所以直接读。
		String appName = environment.getProperty(CommonConstants.SPRING_APP_NAME_KEY);
		if (StrUtil.isBlank(appName)) {
			throw new IllegalArgumentException("服务名 spring.application.name is empty.");
		}
		// 读取系统配置的日志目录，默认为项目下 logs
		String logBase = environment.getProperty(CommonConstants.LOGGING_FILE_PATH, CommonConstants.DEFAULT_LOG_DIR);
		// 激活的环境
		String[] activeProfiles = environment.getActiveProfiles();
		// 判断环境:dev、test、ontest、prod
		List<String> profiles = Arrays.asList(activeProfiles);
		// 预设的环境
		List<String> presetProfiles = DryadEnv.getEnvList();
		// 交集
		presetProfiles.retainAll(profiles);
		// 当前使用
		List<String> activeProfileList = new ArrayList<>(profiles);
		Function<Object[], String> joinFun = StringUtils::arrayToCommaDelimitedString;
		String activeProfile;
		if (presetProfiles.isEmpty()) {
			throw new IllegalArgumentException("环境变量 spring active profile is null.");
		} else if (presetProfiles.size() == 1) {
			activeProfile = presetProfiles.get(0);
		} else {
			// 同时存在dev、test、ontest、prod环境时
			throw new IllegalArgumentException("同时存在环境变量:[" + joinFun.apply(activeProfiles) + "]");
		}
		// 添加启动目录打印
		String startJarPath = DryadLauncher.class.getResource(StrUtil.SLASH).getPath().split(EXCLAMATION_MARK)[0];
		String activePros = joinFun.apply(activeProfileList.toArray());
		System.err.printf("---[%s]---启动中，读取到的环境变量:[%s]，jar地址:[%s]---%n", appName, activePros, startJarPath);
		System.err.printf("---OS系统信息:[%s].", SystemUtil.getOsInfo().toString());
		// 工作默认为 mac 和 Windows
		boolean isLocalDev = OSUtil.isLocalDev();

		Properties properties = System.getProperties();
		// 设定到 sys 中供 使用
		properties.setProperty(CommonConstants.SPRING_APP_NAME_KEY, appName);
		properties.setProperty(CommonConstants.ENV_KEY, activeProfile);
		// https://github.com/alibaba/druid/issues/3873
		properties.setProperty("druid.mysql.usePingMethod", "false");
		properties.setProperty(CommonConstants.LOGGING_FILE_PATH,logBase);

		// 默认的属性配置，级别低于 yml
		Properties defaultProperties = new Properties();
		defaultProperties.setProperty(CommonConstants.IS_LOCAL_KEY, String.valueOf(isLocalDev));
		// 预设请求日志级别
		DryadEnv env = DryadEnv.of(activeProfile);
		// 使用 builder 的 props，优先级低，log.request.level=xxx
		defaultProperties.setProperty(DryadLogLevel.REQ_LOG_PREFIX + ".level", env.getReqLogLevel().name());
		MutablePropertySources propertySources = environment.getPropertySources();
		propertySources.addLast(new PropertiesPropertySource("dryadDefaultProperties", defaultProperties));
	}

}
